package com.ydlclass.discovery.impl;

import com.ydlclass.Constant;
import com.ydlclass.ServiceConfig;
import com.ydlclass.YrpcBootstrap;
import com.ydlclass.discovery.AbstractRegistry;
import com.ydlclass.exceptions.DiscoveryException;
import com.ydlclass.exceptions.NetworkException;
import com.ydlclass.utils.NetUtils;
import com.ydlclass.utils.zookeeper.ZookeeperNode;
import com.ydlclass.utils.zookeeper.ZookeeperUtils;
import com.ydlclass.watch.UpAndDownWatcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.stream.Collectors;

/**
 * zookeeper注册中心实现
 * @Author duWenJian
 * @Date 2024/2/15 22:20
 * @Version 1.0
 */
@Slf4j
public class ZookeeperRegistry extends AbstractRegistry {

    private ZooKeeper zooKeeper ;

    public ZookeeperRegistry() {
        this.zooKeeper = ZookeeperUtils.createZookeeper();
    }

    public ZookeeperRegistry(String connectString, int timeOut) {
        this.zooKeeper = ZookeeperUtils.createZookeeper(connectString,timeOut);
    }

    @Override
    public void register(ServiceConfig<?> service) {
        // 服务名称的节点 /yrpc-metadata/providers/service.getInterface(接口名称)
        String parentNode = Constant.BASE_PROVIDERS_PATH + "/" + service.getInterface().getName();
        if (!ZookeeperUtils.exists(zooKeeper,parentNode,null)) {
            ZookeeperNode zookeeperNode = new ZookeeperNode(parentNode, null);
            // 不存在新建节点
            ZookeeperUtils.createNode(zooKeeper,zookeeperNode,null, CreateMode.PERSISTENT);
        }
        // 分组节点
        parentNode = parentNode + "/" + service.getGroup();
        if (!ZookeeperUtils.exists(zooKeeper,parentNode,null)) {
            ZookeeperNode zookeeperNode = new ZookeeperNode(parentNode, null);
            // 不存在新建节点
            ZookeeperUtils.createNode(zooKeeper,zookeeperNode,null, CreateMode.PERSISTENT);
        }

        // 创建本机的临时节点,ip:port,
        // 服务提供方那个的端口一般是自己设定的，我们还需要一个获取ip的方法
        // ip我们通常是需要一个局域网ip，不是127.0.0.1,也不是ipv6
        // 192.168.26.1

        // 服务名称的节点 /yrpc-metadata/providers/service.getInterface(接口名称)/192.168.26.1:2181
        String node  = parentNode + "/" + NetUtils.getIp() + ":" + YrpcBootstrap.getInstance().getConfiguration().getPort();
        if (!ZookeeperUtils.exists(zooKeeper,node,null)) {
            ZookeeperNode zookeeperNode = new ZookeeperNode(node, null);
            // 不存在新建节点,创建一个临时节点
            ZookeeperUtils.createNode(zooKeeper,zookeeperNode,null, CreateMode.EPHEMERAL);
        }

        if (log.isDebugEnabled()) {
            log.debug("服务:{}已经被注册", service.getInterface().getName());
        }
    }

    @Override
    public List<InetSocketAddress> lookup(String serviceName,String group) {

        // 1、找到服务对应的节点 /yrpc-metadata/providers/service.getInterface(接口名称)
        String ServiceNode = Constant.BASE_PROVIDERS_PATH + "/" + serviceName + "/" + group;
        // 2、从zk中获取他的子节点  192.168.124.2:2181
        List<String> childrenList = ZookeeperUtils.getChildren(zooKeeper, ServiceNode, new UpAndDownWatcher());
        List<InetSocketAddress> collect = childrenList.stream().map(ipString -> {
            String[] ipAndPort = ipString.split(":");
            String ip = ipAndPort[0];
            int port = Integer.parseInt(ipAndPort[1]);
            Integer.getInteger("8088");
            InetSocketAddress address = new InetSocketAddress(ip, port);
            return address;
        }).collect(Collectors.toList());
        if (collect.size() == 0 ){
            throw new DiscoveryException("该节点下未发现任何主机");
        }
        // todo q: 我们每次调用相关方法的时候都需要去注册中心拉取服务列表吗?  本地缓存 + watcher
        //         我们如何合理的选取一个可用的服务而不是每次选择第一个？ 负载均衡策略
        return collect;
    }
}
